数据结构(三) 字符串模式匹配KMP和基于哈希的匹配
没想到吧,竟然是同一天写的,先安利一个kmp视频,看完之后你看代码就有感觉了。
但是还是感觉哈希流批,万物基于哈希(滑稽)
###链接 B站链接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
| #include <stdio.h> #include <stdlib.h> #include <string.h>
//用c++的编译器吧,这里我用到了动态内存 int *next;
void getNext(char* p) { int lenp = strlen(p); next[0] = -1; //第一个是未知的,就放上-1 int k = -1;//指针指在字符串最外面 int j = 0; //指针指在首地址上 while (j < lenp - 1) { //p[k]表示前缀,p[j]表示后缀 if (k == -1 || p[j] == p[k]) { ++k; ++j; next[j] = k; } else { k = next[k]; } } }
int Kmp(char* s, char* p) { int i = 0; int j = 0; int lens = strlen(s); int lenp = strlen(p); while (i < lens && j < lenp) { //如果j = -1,或者当前字符匹配成功即 S[i] == P[j],都令指针移动 if (j == -1 || s[i] == p[j]) { i++; j++; } else { //如果j != -1,且当前字符匹配失败,则令 i 指针不懂,j 回退 j = next[j]; //next[j]即为j所对应的next值 } } if (j == lenp) return i - j; //返回下标 else return -1; }
int main() { char str1[1024]="helloOWorldNotheloWhy??helhellelo"; char str2[1024]="hellelo";
next=new int[strlen(str2)+1];//next 数组长度应该比匹配串大一
getNext(str2);
printf("%d",Kmp(str1,str2)); delete[] next; return 0; }
哈希匹配
#include <stdio.h> #include <stdlib.h> #include <string.h>
//基于哈希的模式匹配
typedef unsigned long long ULL;//用编译器最大的数据类型 2^64
const ULL HashConst=100000007;//哈希基数 mod hashConst
int hash_machting(char *a,char *b)//这次是判a是否在b中出现 { int lena=strlen(a); int lenb=strlen(b);
if(lena>lenb) return -1;//a太长了
ULL t=1; //计算哈希计数的lena次方 for(int i=0;i<lena;++i) t*=HashConst;
//计算a和b为lena的前缀对应的哈希值 ULL ah=0,bh=0; for(int i=0;i<lena;++i) ah=ah*HashConst+a[i]; for(int i=0;i<lena;++i) bh=bh*HashConst+b[i];
//匹配 更新哈希值 for(int i=0;i+lena<=lenb;i++) { if(ah==bh) return i; if(i+lena<lenb) bh=bh*HashConst+b[i+lena]-b[i]*t; } return -1; }
int main() { char str1[1024]="helloOWorldNotheloWhy??helhellelo"; char str2[1024]="hellelo";
printf("%d\n",hash_machting(str2,str1)); return 0; }
|